home *** CD-ROM | disk | FTP | other *** search
Wrap
/* SpriteToolBoxSampleCode.c This sample code shows how the sprite toolbox may be used by an application to create a simple sprite animation (one which is not contained in a QuickTime movie ). */ #include <Fonts.h> #include <Movies.h> void CreateSpriteStuff( Rect *windowBounds ); void CreateSprites( void ); void MoveSprites( void ); void DisposeEverything( void ); OSErr ExtractCompressData( PicHandle thePict, Handle *dataOut, ImageDescriptionHandle *idh ); pascal void extractStdPix( PixMap *src, Rect *srcRect, MatrixRecord *matrix, short mode, RgnHandle mask, PixMap *matte, Rect *matteRect, short flags ); void MakePictTransparent( PicHandle pic, RGBColor *keyColor ); // exception handling macros #define FailIf(a, e) {if (a) { err = e; goto bail; }} #define FailOSErr(a) {if (err = a) goto bail;} #define FailMemErr(a) {a; if (err = MemError()) goto bail;} // constants #define kNumSprites 4 #define kNumSpaceShipImages 24 #define kBackgroundPictID 158 #define kFirstSpaceShipPictID (kBackgroundPictID + 1) #define kSpaceShipWidth 106 #define kSpaceShipHeight 80 // lots of globals GWorldPtr spritePlane = nil; SpriteWorld gSpriteWorld = nil; Rect gBounceBox; Sprite gSprites[kNumSprites]; Rect gDestRects[kNumSprites]; Point gDeltas[kNumSprites]; short gCurrentImages[kNumSprites]; ImageSequence gDecompressSeqs[kNumSpaceShipImages]; Handle gCompressedPictures[kNumSpaceShipImages]; ImageDescriptionHandle gImageDescriptions[kNumSpaceShipImages]; RGBColor gBackgroundColor; void main( void ) { Rect bounds; WindowPtr w; InitGraf( &qd.thePort ); InitFonts(); InitWindows(); InitMenus(); TEInit(); InitDialogs(0L); InitCursor(); MaxApplZone(); EnterMovies(); // create a window SetRect( &bounds, 64, 64, 64 + 512, 64 + 480 ); w = NewCWindow( nil, &bounds, "\pClick Mouse to Quit", false, 0, (WindowPtr)-1, true, 0 ); if ( !w ) return; SetPort( w ); AlignWindow( w, true, nil, nil ); CreateSpriteStuff( &bounds ); ShowWindow( w ); while ( ! Button() ) { MoveSprites(); SpriteWorldIdle( gSpriteWorld, 0, 0 ); } DisposeEverything(); DisposeWindow( w ); ExitMovies(); } void CreateSpriteStuff( Rect *windowBounds ) { OSErr err; Rect bounds; bounds = *windowBounds; OffsetRect( &bounds, -bounds.left, -bounds.top ); gBounceBox = bounds; InsetRect( &gBounceBox, 16, 16 ); NewGWorld( &spritePlane, 8, &bounds, nil, nil, useTempMem ); if ( spritePlane == nil ) NewGWorld( &spritePlane, 8, &bounds, nil, nil, 0 ); if ( spritePlane ) { LockPixels( spritePlane->portPixMap ); gBackgroundColor.red = gBackgroundColor.green = gBackgroundColor.blue = 0; err = NewSpriteWorld( &gSpriteWorld, (CGrafPtr)qd.thePort, spritePlane, &gBackgroundColor, nil ); CreateSprites(); } } void CreateSprites( void ) { long i; Handle compressedData = nil; PicHandle picture; CGrafPtr savePort; GDHandle saveGD; OSErr err; RGBColor keyColor; SetRect( &gDestRects[0], 132, 132, 132 + kSpaceShipWidth, 132 + kSpaceShipHeight ); SetRect( &gDestRects[1], 50, 50, 50 + kSpaceShipWidth, 50 + kSpaceShipHeight ); SetRect( &gDestRects[2], 100, 100, 100 + kSpaceShipWidth, 100 + kSpaceShipHeight ); SetRect( &gDestRects[3], 130, 130, 130 + kSpaceShipWidth, 130 + kSpaceShipHeight ); gDeltas[0].h = -3; gDeltas[0].v = 0; gDeltas[1].h = -5; gDeltas[1].v = 3; gDeltas[2].h = 4; gDeltas[2].v = -6; gDeltas[3].h = 6; gDeltas[3].v = 4; gCurrentImages[0] = 0; gCurrentImages[1] = kNumSpaceShipImages / 4; gCurrentImages[2] = kNumSpaceShipImages / 2; gCurrentImages[3] = kNumSpaceShipImages * 4 / 3; keyColor.red = keyColor.green = keyColor.blue = 0xFFFF; // recompress PICTS for ( i = 0; i < kNumSpaceShipImages; i++ ) { picture = (PicHandle) GetPicture( i + kFirstSpaceShipPictID ); DetachResource( (Handle)picture ); MakePictTransparent( picture, &keyColor ); ExtractCompressData( picture, &gCompressedPictures[i], &gImageDescriptions[i] ); HLock( gCompressedPictures[i] ); KillPicture( picture ); } // create the sprites for our sprite world for ( i = 0; i < kNumSprites; i++ ) { MatrixRecord matrix; SetIdentityMatrix( &matrix ); matrix.matrix[2][0] = ((long)gDestRects[i].left << 16); matrix.matrix[2][1] = ((long)gDestRects[i].top << 16); err = NewSprite( &(gSprites[i]), gSpriteWorld, gImageDescriptions[0], *gCompressedPictures[0], &matrix, true, i ); } } void MoveSprites( void ) { short i; MatrixRecord matrix; SetIdentityMatrix( &matrix ); for ( i = 0; i < kNumSprites; i++ ) { OffsetRect( &gDestRects[i], gDeltas[i].h, gDeltas[i].v ); if ( (gDestRects[i].right >= gBounceBox.right ) || (gDestRects[i].left <= gBounceBox.left) ) gDeltas[i].h = -gDeltas[i].h; if ( (gDestRects[i].bottom >= gBounceBox.bottom ) || (gDestRects[i].top <= gBounceBox.top) ) gDeltas[i].v = -gDeltas[i].v; matrix.matrix[2][0] = ((long)gDestRects[i].left << 16); matrix.matrix[2][1] = ((long)gDestRects[i].top << 16); SetSpriteProperty( gSprites[i], kSpritePropertyMatrix, &matrix ); // change the sprites image too gCurrentImages[i]++; if ( gCurrentImages[i] >= (kNumSpaceShipImages * (i+1)) ) gCurrentImages[i] = 0; SetSpriteProperty( gSprites[i], kSpritePropertyImageDataPtr, *gCompressedPictures[gCurrentImages[i] / (i+1)] ); } } void DisposeEverything( void ) { short i; for ( i = 0; i < kNumSprites; i++ ) { if ( gCompressedPictures[i] ) DisposeHandle( gCompressedPictures[i] ); if ( gImageDescriptions[i] ) DisposeHandle( (Handle)gImageDescriptions[i] ); if ( gSprites[i] ) DisposeSprite( gSprites[i] ); } if ( gSpriteWorld ) DisposeSpriteWorld( gSpriteWorld ); } // the routines below recompress a PICT using the animation compressor typedef struct { CGrafPort tempPort; Handle data; ImageDescriptionHandle idh; } extractPictRecord; #define compressDepth 16 #define compressType 'rle ' OSErr ExtractCompressData( PicHandle thePict, Handle *dataOut, ImageDescriptionHandle *idh ) { OSErr err = noErr; extractPictRecord state; CQDProcs procs; GrafPtr savePort; Rect bounds; if ( dataOut ) *dataOut = nil; if ( idh ) *idh = nil; GetPort( &savePort ); OpenCPort( &state.tempPort ); SetStdCProcs( &procs ); procs.newProc1 = (UniversalProcPtr)extractStdPix; state.tempPort.grafProcs = &procs; state.data = nil; state.idh = nil; SetPort( (GrafPtr)&state.tempPort ); HidePen(); bounds = (**thePict).picFrame; DrawPicture(thePict, &bounds); bail: SetPort( savePort ); CloseCPort( &state.tempPort ); *dataOut = state.data; *idh = state.idh; return err; } pascal void extractStdPix( PixMap *src, Rect *srcRect, MatrixRecord *matrix, short mode, RgnHandle mask, PixMap *matte, Rect *matteRect, short flags ) { #pragma unused(srcRect,matrix,mode,mask,matte,matteRect,flags) extractPictRecord *state; GetPort( (GrafPtr *)&state ); if ( state->idh == nil ) { ImageDescriptionHandle desc; Ptr data; long bufferSize; if ( GetCompressedPixMapInfo(src, &desc, &data, &bufferSize, nil, nil) == noErr ) { state->idh = desc; HandToHand( (Handle *)&state->idh ); PtrToHand( data, &state->data, bufferSize ); } } } void MakePictTransparent( PicHandle pic, RGBColor *keyColor ) { OSErr err; CGrafPtr savePort; GDHandle saveGD; GWorldPtr gw = nil; Rect bounds; ImageSequence seq = 0; ImageDescriptionHandle desc = nil; Ptr data = 0; long dataSize; UInt8 similarity; PicHandle newPict = nil; RGBColor saveBackColor; GetGWorld( &savePort, &saveGD ); bounds = (**(PicHandle)pic).picFrame; OffsetRect( &bounds, -bounds.left, -bounds.top ); err = NewGWorld( &gw, compressDepth, &bounds, nil, nil, useTempMem ); if (err) err = NewGWorld( &gw, compressDepth, &bounds, nil, nil, 0 ); LockPixels( gw->portPixMap ); SetGWorld( gw, nil ); GetBackColor( &saveBackColor ); RGBBackColor( keyColor ); EraseRect( &bounds ); RGBBackColor( &saveBackColor ); desc = (ImageDescriptionHandle)NewHandleClear( sizeof(ImageDescription) ); if ( err = MemError() ) goto bail; err = CompressSequenceBegin( &seq, gw->portPixMap, nil, &bounds, nil, compressDepth, compressType, 0, codecMaxQuality, codecMaxQuality, 0, nil, 0, desc ); if (err) goto bail; err = GetMaxCompressionSize( gw->portPixMap, &bounds, compressDepth, codecMaxQuality, compressType, 0, &dataSize ); if ( err ) goto bail; data = NewPtr( dataSize ); if ( err = MemError() ) goto bail; err = CompressSequenceFrame( seq, gw->portPixMap, &bounds, codecFlagUpdatePrevious, data, &dataSize, &similarity, nil ); if ( err ) goto bail; DrawPicture( pic, &bounds ); err = CompressSequenceFrame( seq, gw->portPixMap, &bounds, codecFlagUpdatePrevious, data, &dataSize, &similarity, nil ); if ( err ) goto bail; CDSequenceEnd( seq ); seq = 0; newPict = OpenPicture( &bounds ); err = DecompressImage( data, desc, gw->portPixMap, &bounds, &bounds, ditherCopy, nil ); ClosePicture(); if ( err ) goto bail; SetHandleSize( (Handle)pic, 0 ); HandAndHand( (Handle)newPict, (Handle)pic ); bail: CDSequenceEnd( seq ); SetGWorld( savePort, saveGD ); if ( gw ) DisposeGWorld( gw ); DisposeHandle( (Handle)desc ); if ( data ) DisposePtr( data ); KillPicture( newPict ); return; }